home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’94 / [√] Distribution Restricted! / Christian Ruse / Fourier Paper + Apps / nih-image154_source.sea / V1.54 Source / Lut.p < prev    next >
Text File  |  1994-01-10  |  48KB  |  1,992 lines

  1. unit Lut;
  2. {This file contains routines that deal with the video Look-Up Table(LUT).}
  3.  
  4. interface
  5.  
  6.     uses
  7.         QuickDraw, Palettes, Picker, PrintTraps, globals, Utilities, Graphics;
  8.  
  9.     function GetPseudoColorIndex: integer;
  10.     function isGrayScaleLUT: boolean;
  11.     procedure DoMouseDownInLUT (event: EventRecord);
  12.     procedure DoCopyColor;
  13.     procedure PasteColor;
  14.     procedure ShowRGBValues (index: integer);
  15.     procedure InvertPalette;
  16.     procedure FindPoints (var x1, y1, x2, y2: integer);
  17.     procedure UpdateMap;
  18.     procedure ResetGraymap;
  19.     procedure DrawMap;
  20.     procedure DoMouseDownInMap;
  21.     procedure EnableThresholding (level: integer);
  22.     procedure DisableThresholding;
  23.     procedure DrawLUT;
  24.     procedure UpdateLUT;
  25.     procedure LoadColorTable (theColorTable: CTabHandle);
  26.     function LoadCLUTResource (id: integer): boolean;
  27.     procedure GetLookupTable (var table: LookupTable);
  28.     procedure RedrawLUTWindow;
  29.     procedure DrawDensitySlice (OptionKey: boolean);
  30.     procedure SelectLutTool;
  31.     procedure EnableDensitySlice;
  32.     procedure SetupPseudocolor;
  33.     procedure DoImportLut (fname: str255; vnum: integer);
  34.     procedure OpenOldPalette (fname: str255; RefNum: integer);
  35.     procedure OpenNewPalette (fname: str255; RefNum: integer);
  36.     procedure OpenColorTable (fname: str255; RefNum: integer);
  37.     procedure ImportPalette (FileType: OSType; fname: str255; vnum: integer);
  38.     procedure GetColorTable (id: integer);
  39.     procedure GetLutResource (id: integer);
  40.     procedure DrawScale;
  41.     procedure MakeSpectrum;
  42.     function GetColorTableItem (ctab: ColorTableType): integer;
  43.     procedure SwitchColorTables (item: integer; update: boolean);
  44.     procedure InitPaletteHeader (var hdr: PaletteHeader);
  45.     procedure ResetMap;
  46.     procedure DoLutOptions;
  47.  
  48.  
  49.  
  50.  
  51. implementation
  52.  
  53.  
  54.     function GetPseudoColorIndex: integer;
  55.         var
  56.             index: integer;
  57.     begin
  58.         with info^ do begin
  59.                 index := trunc((nColors) * (ForegroundIndex - ColorStart) / (ColorEnd - ColorStart + 1));
  60.                 if index < 0 then
  61.                     index := 0;
  62.                 if index > (nColors - 1) then
  63.                     index := nColors - 1;
  64.                 GetPseudoColorIndex := index;
  65.             end;
  66.     end;
  67.  
  68.  
  69.     procedure UpdateLUT;
  70.         var
  71.             MaxStart, i, v, index, last: integer;
  72.             inc, sIndex: LongInt;
  73.     begin
  74.         with info^ do begin
  75.                 sIndex := 0;
  76.                 if ColorEnd > ColorStart then
  77.                     inc := LongInt(nColors) * 10000 div (ColorEnd - ColorStart)
  78.                 else
  79.                     inc := 2560000;
  80.                 if ColorStart < 0 then
  81.                     sIndex := -ColorStart * Inc
  82.                 else
  83.                     sIndex := 0;
  84.                 last := nColors - 1;
  85.                 for i := 0 to 255 do
  86.                     with cTable[i].rgb do begin
  87.                             if (i < ColorStart) or (i > ColorEnd) then begin
  88.                                     if i < ColorStart then
  89.                                         cTable[i].rgb := FillColor1
  90.                                     else
  91.                                         cTable[i].rgb := FillColor2;
  92.                                 end
  93.                             else begin
  94.                                     index := sIndex div 10000;
  95.                                     if index > last then
  96.                                         index := last;
  97.                                     Red := bsl(RedLUT[index], 8);
  98.                                     Green := bsl(GreenLUT[index], 8);
  99.                                     Blue := bsl(BlueLUT[index], 8);
  100.                                     sIndex := sIndex + inc;
  101.                                 end;
  102.                         end; {for}
  103.                 if ColorStart = ColorEnd then
  104.                     cTable[ColorStart].rgb := FillColor2
  105.                 else
  106.                     Thresholding := false;
  107.                 LoadLUT(cTable);
  108.                 IdentityFunction := false;
  109.             end;
  110.     end;
  111.  
  112.  
  113.     function GetVLoc: integer;
  114.         var
  115.             loc: point;
  116.             vloc: integer;
  117.     begin
  118.         GetMouse(loc);
  119.         vloc := loc.v;
  120.         if vloc > 255 then
  121.             vloc := 255;
  122.         if vloc <= 0 then
  123.             vloc := 0;
  124.         GetVLoc := vloc;
  125.     end;
  126.  
  127.  
  128.     procedure GetNewColor (var color: RGBColor);
  129.         var
  130.             where: point;
  131.             inRGBColor, OutRGBColor: RGBColor;
  132.     begin
  133.         inRGBColor := color;
  134.         outRGBColor := color;
  135.         where.h := 0;
  136.         where.v := 0;
  137.         InitCursor;
  138.         if GetColor(where, 'Pick a new color...', inRGBColor, outRGBColor) then
  139.             color := outRGBColor;
  140.     end;
  141.  
  142.  
  143.     procedure EditPseudoColors;
  144.         var
  145.             where: point;
  146.             inRGBColor, OutRGBColor: RGBColor;
  147.             index, mloc: integer;
  148.     begin
  149.         SetupLUTUndo;
  150.         with info^ do begin
  151.                 SetPort(LUTWindow);
  152.                 mloc := getvloc;
  153.                 if mloc < ColorStart then begin
  154.                         GetNewColor(FillColor1);
  155.                         UpdateLUT;
  156.                         exit(EditPseudoColors);
  157.                     end;
  158.                 if mloc > ColorEnd then begin
  159.                         GetNewColor(FillColor2);
  160.                         UpdateLUT;
  161.                         exit(EditPseudoColors);
  162.                     end;
  163.                 index := GetPseudoColorIndex;
  164.                 with inRGBColor do begin
  165.                         red := bsl(RedLUT[index], 8);
  166.                         green := bsl(GreenLUT[index], 8);
  167.                         blue := bsl(BlueLUT[index], 8);
  168.                     end;
  169.                 outRGBColor := inRGBColor;
  170.                 where.h := 0;
  171.                 where.v := 0;
  172.                 InitCursor;
  173.                 if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then begin
  174.                         with outRGBColor do begin
  175.                                 RedLUT[index] := bsr(red, 8);
  176.                                 GreenLUT[index] := bsr(green, 8);
  177.                                 BlueLUT[index] := bsr(blue, 8);
  178.                             end;
  179.                         changes := true;
  180.                     end;
  181.                 ColorTable := CustomTable;
  182.                 LutMode := PseudoColor;
  183.                 UpdateLUT;
  184.             end; {with}
  185.     end;
  186.  
  187.  
  188.     function EditSliceColor: boolean;
  189.         var
  190.             where: point;
  191.             inRGBColor, OutRGBColor: RGBColor;
  192.             vloc: integer;
  193.     begin
  194.         SetPort(LUTWindow);
  195.         vloc := getvloc;
  196.         if (vloc >= SliceStart) and (vloc <= SliceEnd) then begin
  197.                 GetNewColor(SliceColor);
  198.                 DrawDensitySlice(false);
  199.                 EditSliceColor := true
  200.             end
  201.         else
  202.             EditSliceColor := false;
  203.     end;
  204.  
  205.  
  206.     procedure ShowLUTValues (tStart, tEnd: integer);
  207.         var
  208.             tPort: GrafPtr;
  209.             value: extended;
  210.             range, NewMin, NewMax: LongInt;
  211.     begin
  212.         with info^ do begin
  213.                 GetPort(tPort);
  214.                 SetPort(ValuesWindow);
  215.                 TextSize(9);
  216.                 TextFont(Monaco);
  217.                 TextMode(SrcCopy);
  218.                 MoveTo(xValueLoc, ValuesVStart);
  219.                 if DataType <> EightBits then begin
  220.                         range := CurrentMax - CurrentMin;
  221.                         if tEnd < 255 then
  222.                             NewMin := CurrentMin + round(((255 - tEnd) / 255) * range)
  223.                         else
  224.                             NewMin := CurrentMin;
  225.                         DrawLong(NewMin);
  226.                         DrawString('    ');
  227.                         MoveTo(xValueLoc, ValuesVStart + 10);
  228.                         if tStart > 0 then
  229.                             NewMax := CurrentMax - round((tStart / 255) * range)
  230.                         else
  231.                             NewMax := CurrentMax;
  232.                         DrawLong(NewMax);
  233.                         DrawString('    ');
  234.                         SetPort(tPort);
  235.                         exit(ShowLUTValues);
  236.                     end;
  237.                 if DensityCalibrated then begin
  238.                         if tStart >= 0 then
  239.                             value := cvalue[tStart]
  240.                         else
  241.                             value := cvalue[0];
  242.                         DrawReal(value, 5, 2);
  243.                         DrawString(' (');
  244.                         DrawReal(tStart, 3, 0);
  245.                         DrawString(')');
  246.                     end
  247.                 else
  248.                     DrawReal(tStart, 3, 0);
  249.                 DrawString('    ');
  250.                 MoveTo(xValueLoc, ValuesVStart + 10);
  251.                 if DensityCalibrated then begin
  252.                         if tEnd <= 255 then
  253.                             value := cvalue[tEnd]
  254.                         else
  255.                             value := cvalue[255];
  256.                         DrawReal(value, 5, 2);
  257.                         DrawString(' (');
  258.                         DrawReal(tEnd, 3, 0);
  259.                         DrawString(')');
  260.                     end
  261.                 else
  262.                     DrawReal(tEnd, 3, 0);
  263.                 DrawString('    ');
  264.                 SetPort(tPort);
  265.             end;
  266.     end;
  267.  
  268.  
  269.     procedure ShowRGBValues (index: integer);
  270.         var
  271.             tPort: GrafPtr;
  272.             vloc: integer;
  273.     begin
  274.         with info^ do begin
  275.                 GetPort(tPort);
  276.                 SetPort(ValuesWindow);
  277.                 TextSize(9);
  278.                 TextFont(Monaco);
  279.                 TextMode(SrcCopy);
  280.                 vloc := ValuesVStart;
  281.                 MoveTo(xValueLoc, vloc);
  282.                 DrawLong(index);
  283.                 DrawString('    ');
  284.                 if Info^.DensityCalibrated then begin
  285.                         vloc := vloc + 10;
  286.                         MoveTo(xValueLoc, vloc);
  287.                         DrawReal(cvalue[index], 1, precision);
  288.                         DrawString('    ');
  289.                     end;
  290.                 vloc := vloc + 10;
  291.                 MoveTo(xValueLoc, vloc);
  292.                 DrawRGB(index);
  293.                 DrawString('    ');
  294.                 SetPort(tPort);
  295.             end;
  296.     end;
  297.  
  298.  
  299.     procedure FindPoints (var x1, y1, x2, y2: integer);
  300.     begin
  301.         with info^ do begin
  302.                 if ColorStart >= 0 then begin
  303.                         x1 := ColorStart;
  304.                         y1 := 0;
  305.                     end
  306.                 else begin
  307.                         x1 := 0;
  308.                         if ColorEnd > ColorStart then
  309.                             y1 := -ColorStart * 255 div (ColorEnd - ColorStart)
  310.                         else
  311.                             y1 := 0;
  312.                     end;
  313.                 if ColorEnd <= 255 then begin
  314.                         x2 := ColorEnd;
  315.                         y2 := 255;
  316.                     end
  317.                 else begin
  318.                         x2 := 255;
  319.                         if ColorEnd > ColorStart then
  320.                             y2 := 255 * (255 - ColorStart) div (ColorEnd - ColorStart)
  321.                         else
  322.                             y2 := 255;
  323.                     end;
  324.             end;
  325.     end;
  326.  
  327.  
  328.     procedure UpdateMap;
  329.         var
  330.             r: rect;
  331.             x, y, i, h1, h2, h3, v1, v2, v3, dx, dy: integer;
  332.             xcenter, ycenter, brightness, islope, thumb: integer;
  333.             width, max: integer;
  334.             table: LookupTable;
  335.             hrect: rect;
  336.             slope: extended;
  337.             area, value, sum: LongInt;
  338.             p1x, p1y, p2x, p2y: integer;
  339.     begin
  340.         with info^ do begin
  341.                 FindPoints(p1x, p1y, p2x, p2y);
  342.                 SetPort(MapWindow);
  343.                 PenNormal;
  344.                 EraseRect(MapRect2);
  345.                 FrameRect(MapRect);
  346.                 if LutMode = CustomGrayscale then begin
  347.                         GetLookupTable(table);
  348.                         MoveTo(gmRectLeft, gmRectBottom - 1);
  349.                         for i := 0 to 63 do begin
  350.                                 x := gmRectLeft + i;
  351.                                 y := gmRectBottom - table[i * 4] div 4 - 1;
  352.                                 LineTo(x, y);
  353.                             end;
  354.                         EraseRect(gmSlide1i);
  355.                         EraseRect(gmSlide2i);
  356.                         exit(UpdateMap);
  357.                     end;
  358.                 h1 := gmRectLeft + p1x div 4;
  359.                 v1 := gmRectBottom - 1 - (p1y div 4);
  360.                 h2 := gmRectLeft + p2x div 4;
  361.                 v2 := gmRectBottom - 1 - (p2y div 4);
  362.                 MoveTo(gmRectLeft, gmRectBottom - 1);
  363.                 LineTo(h1, v1);
  364.                 LineTo(h2, v2);
  365.                 LineTo(gmRectRight - 1, gmRectTop);
  366.                 SetRect(hrect, h1 - 1, v1 - 1, h1 + 2, v1 + 2);
  367.                 PaintRect(hrect); {First handle}
  368.                 SetRect(hrect, h2 - 1, v2 - 1, h2 + 2, v2 + 2);
  369.                 PaintRect(hrect); {Last handle}
  370.                 dx := p2x - p1x;
  371.                 dy := p2y - p1y;
  372.                 xcenter := p1x + dx div 2;
  373.                 ycenter := p1y + dy div 2;
  374.                 h3 := gmRectLeft + xcenter div 4;
  375.                 v3 := gmRectBottom - 1 - (ycenter div 4);
  376.                 SetRect(hrect, h3 - 1, v3 - 1, h3 + 2, v3 + 2);
  377.                 PaintRect(hrect); {Center handle}
  378.                 thumb := gmSlideHeight - 2;
  379.                 max := gmSlideWidth - thumb - 2;
  380.                 width := ColorEnd - ColorStart;
  381.                 brightness := trunc(max * ((ColorStart + width) / (width + 255)));
  382.                 with gmSlide1 do
  383.                     SetRect(hrect, left + brightness + 1, top + 1, left + brightness + thumb + 1, top + thumb + 1);
  384.                 EraseRect(gmSlide1i);
  385.                 PaintRect(hrect);  {Thumb for contrast control}
  386.                 if dx <> 0 then
  387.                     slope := dy / dx
  388.                 else
  389.                     slope := 1000.0;
  390.                 if slope > 1.0 then begin
  391.                         if dy <> 0 then
  392.                             slope := 2.0 - dx / dy
  393.                         else
  394.                             slope := 2.0;
  395.                     end;
  396.                 islope := trunc(slope * 0.5 * (gmSlideWidth - thumb - 2.0));
  397.                 with gmSlide2 do
  398.                     SetRect(hrect, left + islope + 1, top + 1, left + islope + thumb + 1, top + thumb + 1);
  399.                 EraseRect(gmSlide2i);
  400.                 PaintRect(hrect);  {Thumb for contrast control}
  401.             end;
  402.     end;
  403.  
  404.  
  405.     procedure UpdateThreshold;
  406.         var
  407.             level: integer;
  408.     begin
  409.         DrawLabels('Thresh:', '', '');
  410.         ShowMessage('');
  411.         with info^ do
  412.             repeat
  413.                 SetPort(LUTWindow);
  414.                 level := GetVLoc;
  415.                 if level <= 255 then begin
  416.                         ColorStart := level;
  417.                         ColorEnd := level;
  418.                         UpdateMap;
  419.                         UpdateLUT;
  420.                     end;
  421.                 Show1Value(level, NoValue);
  422.             until not Button;
  423.     end;
  424.  
  425.  
  426.     procedure UpdateDensitySlice;
  427.         var
  428.             mloc, saveloc, width, delta: integer;
  429.             adjust: (lower, upper, both);
  430.     begin
  431.         DrawLabels('Lower:', 'Upper:', '');
  432.         SetPort(LUTWindow);
  433.         mloc := getvloc;
  434.         saveloc := mloc;
  435.         width := SliceEnd - SliceStart + 1;
  436.         adjust := lower;
  437.         if mloc > (SliceStart + width div 4) then
  438.             adjust := both;
  439.         if mloc > (SliceEnd - width div 4) then
  440.             adjust := upper;
  441.         while button do begin
  442.                 width := SliceEnd - SliceStart + 1;
  443.                 mloc := getvloc;
  444.                 delta := mloc - saveloc;
  445.                 saveloc := mloc;
  446.                 case adjust of
  447.                     lower:  begin
  448.                             SliceStart := mloc;
  449.                             if SliceStart < 1 then
  450.                                 SliceStart := 1;
  451.                             if SliceStart > SliceEnd then
  452.                                 SliceStart := SliceEnd;
  453.                         end;
  454.                     upper:  begin
  455.                             SliceEnd := mloc;
  456.                             if SliceEnd > 254 then
  457.                                 SliceEnd := 254;
  458.                             if SliceEnd < SliceStart then
  459.                                 SliceEnd := SliceStart;
  460.                         end;
  461.                     both:  begin
  462.                             if mloc <= 1 then begin
  463.                                     SliceStart := 1;
  464.                                     SliceEnd := width;
  465.                                 end
  466.                             else if mloc >= 254 then begin
  467.                                     SliceEnd := 254;
  468.                                     SliceStart := 254 - width + 1;
  469.                                 end
  470.                             else if ((SliceStart + delta) >= 1) and ((SliceEnd + delta) <= 254) then begin
  471.                                     SliceStart := SliceStart + delta;
  472.                                     SliceEnd := SliceEnd + delta;
  473.                                 end;
  474.                         end;
  475.                 end; {case}
  476.                 DrawDensitySlice(OptionKeyDown);
  477.                 ShowLUTValues(SliceStart, SliceEnd);
  478.             end; {while}
  479.         DrawDensitySlice(false)
  480.     end;
  481.  
  482.  
  483.     procedure EditExtraColors (entry: integer);
  484.         var
  485.             where: point;
  486.             inRGBColor, OutRGBColor: RGBColor;
  487.     begin
  488.         if (entry <> WhiteIndex) and (entry <> BlackIndex) then begin
  489.                 inRGBColor := ExtraColors[entry];
  490.                 outRGBColor := inRGBColor;
  491.                 where.h := 0;
  492.                 where.v := 0;
  493.                 InitCursor;
  494.                 if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then
  495.                     with info^ do begin
  496.                             ExtraColors[entry] := OutRGBColor;
  497.                             changes := true;
  498.                             LoadLUT(cTable);
  499.                         end
  500.             end
  501.         else
  502.             PutMessage('Sorry, but you can not edit white or black.');
  503.     end;
  504.  
  505.  
  506.     function GetColorFromLUT (DoubleClick: boolean): integer;
  507.         var
  508.             mloc, color, i: integer;
  509.             loc: point;
  510.     begin
  511.         SetPort(LUTWindow);
  512.         GetMouse(loc);
  513.         if loc.v > 255 then begin
  514.                 color := 0;
  515.                 for i := 1 to nExtraColors + 2 do
  516.                     if PtInRect(loc, ExtraColorsRect[i]) then
  517.                         Color := ExtraColorsEntry[i];
  518.                 if DoubleClick then
  519.                     EditExtraColors(color);
  520.                 GetColorFromLUT := color;
  521.             end
  522.         else
  523.             GetColorFromLUT := loc.v;
  524.     end;
  525.  
  526.  
  527.     function isGrayScaleLUT: boolean;
  528.         var
  529.             i: integer;
  530.             GrayScaleLUT: boolean;
  531.     begin
  532.         with info^ do begin
  533.                 GrayscaleLUT := true;
  534.                 i := 0;
  535.                 repeat
  536.                     with cTable[i].rgb do
  537.                         GrayscaleLUT := GrayscaleLUT and (red = green) and (green = blue);
  538.                     i := i + 1;
  539.                 until (i = 256) or not GrayscaleLUT;
  540.                 isGrayScaleLUT := GrayScaleLUT;
  541.             end;
  542.     end;
  543.  
  544.  
  545.     procedure SetupPseudocolor;
  546.         var
  547.             i: integer;
  548.     begin
  549.         with info^ do begin
  550.                 DisableDensitySlice;
  551.                 Thresholding := false;
  552.                 for i := 1 to 254 do
  553.                     with cTable[i].rgb do begin
  554.                             RedLUT[i] := band(bsr(red, 8), 255);
  555.                             GreenLUT[i] := band(bsr(green, 8), 255);
  556.                             BlueLUT[i] := band(bsr(blue, 8), 255);
  557.                         end;
  558.                 RedLUT[0] := RedLUT[1];
  559.                 GreenLUT[0] := GreenLUT[1];
  560.                 BlueLUT[0] := BlueLUT[1];
  561.                 RedLUT[255] := RedLUT[254];
  562.                 GreenLUT[255] := GreenLUT[254];
  563.                 BlueLUT[255] := BlueLUT[254];
  564.                 nColors := 256;
  565.                 ColorStart := 0;
  566.                 ColorEnd := 255;
  567.                 FillColor1 := ctable[1].rgb;
  568.                 FillColor2 := ctable[254].rgb;
  569.                 InvertedColorTable := false;
  570.             end;
  571.     end;
  572.  
  573.  
  574.     procedure ShowLabels;
  575.     begin
  576.         with info^ do
  577.             if DataType <> EightBits then
  578.                 DrawLabels('Min:', 'Max:', '')
  579.             else
  580.                 DrawLabels('Lower:', 'Upper:', '');
  581.     end;
  582.  
  583.  
  584.     procedure AdjustLUT;
  585.         const
  586.             MinWidth = 8;
  587.         var
  588.             mloc, saveloc, width, delta, cstart, cend: integer;
  589.             adjust: (lower, upper, both);
  590.             loc: point;
  591.     begin
  592.         with info^ do begin
  593.                 SetPort(LUTWindow);
  594.                 SetupLutUndo;
  595.                 ShowLabels;
  596.                 mloc := getvloc;
  597.                 saveloc := mloc;
  598.                 cstart := ColorStart;
  599.                 if cstart < 0 then
  600.                     cstart := 0;
  601.                 cend := ColorEnd;
  602.                 if cend > 255 then
  603.                     cend := 255;
  604.                 width := cend - cstart + 1;
  605.                 adjust := lower;
  606.                 if mloc > (cstart + width div 4) then
  607.                     adjust := both;
  608.                 if mloc > (cend - width div 4) then
  609.                     adjust := upper;
  610.                 while button do begin
  611.                         SetPort(LUTWindow);
  612.                         GetMouse(loc);
  613.                         mloc := loc.v;
  614.                         delta := mloc - saveloc;
  615.                         saveloc := mloc;
  616.                         case adjust of
  617.                             lower:  begin
  618.                                     ColorStart := mloc;
  619.                                     cend := ColorEnd;
  620.                                     if cend > 255 then
  621.                                         cend := 255;
  622.                                     if ColorStart > (cend - MinWidth) then
  623.                                         ColorStart := cend - MinWidth;
  624.                                 end;
  625.                             upper:  begin
  626.                                     ColorEnd := mloc;
  627.                                     cstart := ColorStart;
  628.                                     if cstart < 0 then
  629.                                         cstart := 0;
  630.                                     if ColorEnd < (cstart + MinWidth) then
  631.                                         ColorEnd := cstart + MinWidth;
  632.                                 end;
  633.                             both: 
  634.                                 if (mloc >= 0) and (mloc <= 255) then begin
  635.                                         ColorStart := ColorStart + delta;
  636.                                         ColorEnd := ColorEnd + delta;
  637.                                     end;
  638.                         end;
  639.                         UpdateLUT;
  640.                         UpdateMap;
  641.                         ShowLUTValues(ColorStart, ColorEnd);
  642.                     end;
  643.             end; {with info}
  644.     end;
  645.  
  646.  
  647.     procedure RotateLUT;
  648.         var
  649.             vstart, i, j, delta: integer;
  650.             loc: point;
  651.             TempTable: MyCSpecArray;
  652.     begin
  653.         with info^ do begin
  654.                 SetPort(LUTWindow);
  655.                 GetMouse(loc);
  656.                 vstart := loc.v;
  657.                 repeat
  658.                     GetMouse(loc);
  659.                     delta := vstart - loc.v;
  660.                     for i := 1 to 254 do begin {0 is resevred for white and 255 for black}
  661.                             j := i + delta;
  662.                             if j > 254 then
  663.                                 j := j - 254;
  664.                             if j > 254 then
  665.                                 j := 254;
  666.                             if j < 1 then
  667.                                 j := j + 254;
  668.                             if j < 1 then
  669.                                 j := 1;
  670.                             TempTable[i] := cTable[j]
  671.                         end;
  672.                     cTable := TempTable;
  673.                     LoadLUT(cTable);
  674.                     vstart := loc.v;
  675.                 until not button;
  676.                 SetupPseudocolor;
  677.                 ColorTable := CustomTable;
  678.             end;
  679.     end;
  680.  
  681.  
  682.     procedure DoMouseDownInLUT (event: EventRecord);
  683.         var
  684.             color: integer;
  685.             DoubleClick: boolean;
  686.     begin
  687.         with info^ do begin
  688.                 if CurrentTool = PickerTool then
  689.                     DoubleClick := (TickCount - LutTime) < GetDblTime
  690.                 else
  691.                     DoubleClick := false;
  692.                 LutTime := TickCount;
  693.                 if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
  694.                         color := GetColorFromLUT(DoubleClick);
  695.                         if (CurrentTool = eraser) or OptionKeyDown then
  696.                             SetBackgroundColor(color)
  697.                         else
  698.                             SetForegroundColor(color);
  699.                         if not DoubleClick then
  700.                             exit(DoMouseDownInLUT);
  701.                     end;
  702.                 if Thresholding then begin
  703.                         UpdateThreshold;
  704.                         exit(DoMouseDownInLUT)
  705.                     end;
  706.                 if DoubleClick then begin
  707.                         if DensitySlicing and (CurrentTool = PickerTool) then begin
  708.                                 if EditSliceColor then
  709.                                     exit(DoMouseDownInLUT);
  710.                             end;
  711.                         if CurrentTool = PickerTool then begin
  712.                                 EditPseudoColors;
  713.                                 exit(DoMouseDownInLUT)
  714.                             end;
  715.                     end; {if DoubleClick}
  716.                 if ((CurrentTool = LutTool) or (CurrentTool = Wand)) and DensitySlicing then begin
  717.                         UpdateDensitySlice;
  718.                         exit(DoMouseDownInLUT);
  719.                     end;
  720.                 if OptionKeyDown then
  721.                     RotateLUT
  722.                 else
  723.                     AdjustLUT;
  724.             end; {with}
  725.     end;
  726.  
  727.  
  728.     procedure DoCopyColor;
  729.     begin
  730.         with info^ do begin
  731.                 if ForegroundIndex = WhiteIndex then begin
  732.                         ClipboardColor := WhiteRGB;
  733.                         exit(DoCopyColor);
  734.                     end;
  735.                 if ForegroundIndex = BlackIndex then begin
  736.                         ClipboardColor := BlackRGB;
  737.                         exit(DoCopyColor);
  738.                     end;
  739.                 with cTable[ForegroundIndex].rgb do begin
  740.                         ClipboardColor.red := red;
  741.                         ClipboardColor.green := green;
  742.                         ClipboardColor.blue := blue;
  743.                     end;
  744.                 WhatsOnClip := AColor;
  745.                 ClipTextInBuffer := false;
  746.             end;
  747.     end;
  748.  
  749.  
  750.     procedure PasteColor;
  751.         var
  752.             CurrentColorIndex: integer;
  753.     begin
  754.         with info^ do begin
  755.                 if CurrentTool = PickerTool then begin
  756.                         if ForegroundIndex < ColorStart then begin
  757.                                 FillColor1 := ClipboardColor;
  758.                                 UpdateLUT;
  759.                                 exit(PasteColor);
  760.                             end;
  761.                         if ForegroundIndex > ColorEnd then begin
  762.                                 FillColor2 := ClipboardColor;
  763.                                 UpdateLUT;
  764.                                 exit(PasteColor);
  765.                             end;
  766.                         CurrentColorIndex := GetPseudoColorIndex;
  767.                         with ClipboardColor do begin
  768.                                 RedLUT[CurrentColorIndex] := bsr(red, 8);
  769.                                 GreenLUT[CurrentColorIndex] := bsr(green, 8);
  770.                                 BlueLUT[CurrentColorIndex] := bsr(blue, 8);
  771.                             end;
  772.                         ColorTable := CustomTable;
  773.                         UpdateLUT;
  774.                     end
  775.                 else
  776.                     beep;
  777.             end;
  778.     end;
  779.  
  780.  
  781.     procedure InvertPalette;
  782.         var
  783.             TempRed, TempGreen, TempBlue: LutArray;
  784.             i, LastColor: integer;
  785.             TempTable: MyCSpecArray;
  786.             TempFill: rgbColor;
  787.     begin
  788.         with info^ do begin
  789.                 TempRed := RedLUT;
  790.                 TempGreen := GreenLUT;
  791.                 TempBlue := BlueLUT;
  792.                 LastColor := ncolors - 1;
  793.                 for i := 0 to LastColor do begin
  794.                         RedLUT[i] := TempRed[LastColor - i];
  795.                         GreenLUT[i] := TempGreen[LastColor - i];
  796.                         BlueLUT[i] := TempBlue[LastColor - i];
  797.                     end;
  798.                 TempFill := FillColor1;
  799.                 FillColor1 := FillColor2;
  800.                 FillColor2 := TempFill;
  801.                 InvertedColorTable := not InvertedColorTable;
  802.                 IdentityFunction := false;
  803.             end;
  804.     end;
  805.  
  806.  
  807.     procedure DrawMap;
  808.         var
  809.             x, y, i: integer;
  810.             table: LookupTable;
  811.     begin
  812.         SetPort(MapWindow);
  813.         PenNormal;
  814.         TextFont(ApplFont);
  815.         TextSize(9);
  816.         with gmSlide1 do
  817.             MoveTo(left - 6, bottom);
  818.         DrawChar('B');
  819.         with gmSlide2 do
  820.             MoveTo(left - 6, bottom);
  821.         DrawChar('C');
  822.         FrameRect(gmSlide1);
  823.         FrameRect(gmSlide2);
  824.         FrameRect(gmIcon1);
  825.         FrameRect(gmIcon2);
  826.         with gmIcon1 do begin
  827.                 MoveTo(left, top + 10);
  828.                 LineTo(left + 5, top + 10);
  829.                 LineTo(left + 12, top + 3);
  830.                 LineTo(left + gmIconWidth - 1, top + 3);
  831.             end;
  832.         with gmIcon2 do begin
  833.                 MoveTo(left, top + 10);
  834.                 LineTo(left + gmIconWidth div 2, top + 10);
  835.                 LineTo(left + gmIconWidth div 2, top + 3);
  836.                 LineTo(left + gmIconWidth - 1, top + 3);
  837.             end;
  838.         UpdateMap;
  839.         GrayMapReady := true;
  840.     end;
  841.  
  842.  
  843.     procedure ResetGrayMap;
  844.         var
  845.             i: integer;
  846.     begin
  847.         with info^ do begin
  848.                 DisableDensitySlice;
  849.                 for i := 0 to 255 do begin
  850.                         RedLut[i] := 255 - i;
  851.                         GreenLut[i] := 255 - i;
  852.                         BlueLut[i] := 255 - i;
  853.                     end;
  854.                 FillColor1 := WhiteRGB;
  855.                 FillColor2 := BlackRGB;
  856.                 ColorStart := 0;
  857.                 ColorEnd := 255;
  858.                 nColors := 256;
  859.                 ColorTable := CustomTable;
  860.                 LUTMode := Grayscale;
  861.                 UpdateLUT;
  862.                 if GrayMapReady then
  863.                     UpdateMap;
  864.                 IdentityFunction := true;
  865.                 InvertedColorTable := false;
  866.             end;
  867.     end;
  868.  
  869.  
  870.     procedure AdjustBrightness;
  871.         var
  872.             loc, max, thumb, xcenter, ycenter, width: integer;
  873.             p: point;
  874.     begin
  875.         with info^ do begin
  876.                 thumb := gmSlideHeight - 2;
  877.                 max := gmSlideWidth - thumb - 2;
  878.                 width := ColorEnd - ColorStart;
  879.                 ShowLabels;
  880.                 repeat
  881.                     GetMouse(p);
  882.                     loc := p.h - gmSlide1.left - 2;
  883.                     if loc < 0 then
  884.                         loc := 0;
  885.                     if loc > max then
  886.                         loc := max;
  887.                     ColorStart := -width + round((width + 255) * (loc / max));
  888.                     ColorEnd := ColorStart + width;
  889.                     UpdateMap;
  890.                     UpdateLUT;
  891.                     ShowLUTValues(ColorStart, ColorEnd);
  892.                 until not button;
  893.                 IdentityFunction := false;
  894.             end; {with}
  895.     end;
  896.  
  897.  
  898.     procedure AdjustContrast;
  899.         var
  900.             p: point;
  901.             loc, max, HalfMax, thumb: integer;
  902.             slope, center: extended;
  903.     begin
  904.         with info^ do begin
  905.                 thumb := gmSlideHeight - 2;
  906.                 max := gmSlideWidth - thumb - 2;
  907.                 HalfMax := max div 2;
  908.                 center := ColorStart + (ColorEnd - ColorStart) / 2.0;
  909.                 ShowLabels;
  910.                 repeat
  911.                     GetMouse(p);
  912.                     loc := p.h - gmSlide2.left - 2;
  913.                     if loc < 0 then
  914.                         loc := 0;
  915.                     if loc > max then
  916.                         loc := max;
  917.                     if loc <= HalfMax then
  918.                         slope := loc / HalfMax
  919.                     else if loc < max then
  920.                         slope := HalfMax / (max - loc)
  921.                     else
  922.                         slope := 1000.0;
  923.                     if slope > 0.0 then begin
  924.                             ColorStart := round(center - 127.5 / slope);
  925.                             ColorEnd := round(center + 127.5 / slope);
  926.                         end
  927.                     else begin
  928.                             ColorStart := round(center - MaxColor);
  929.                             ColorEnd := round(center + MaxColor);
  930.                         end;
  931.                     if ColorEnd < 0 then
  932.                         ColorEnd := 0;
  933.                     if ColorStart > 255 then
  934.                         ColorStart := 255;
  935.                     UpdateMap;
  936.                     UpdateLUT;
  937.                     ShowLUTValues(ColorStart, ColorEnd);
  938.                 until not button;
  939.                 IdentityFunction := false;
  940.             end; {with}
  941.     end;
  942.  
  943.  
  944.     procedure ConvertMouseToXY (p: point; var x, y: integer);
  945.     begin
  946.         x := (p.h - gmRectLeft) * 4;
  947.         if x < 0 then
  948.             x := 0;
  949.         if x > 255 then
  950.             x := 255;
  951.         y := (gmRectBottom - p.v) * 4;
  952.         if y < 0 then
  953.             y := 0;
  954.         if y > 255 then
  955.             y := 255;
  956.     end;
  957.  
  958.  
  959.     procedure DoFreehandEditing;
  960.         var
  961.             p: point;
  962.             x1, x2, y, i: integer;
  963.             FirstTime: boolean;
  964.     begin
  965.         with info^ do begin
  966.                 LUTMode := CustomGrayscale;
  967.                 SetPort(MapWindow);
  968.                 FirstTime := true;
  969.                 while button do begin
  970.                         x1 := x2;
  971.                         GetMouse(p);
  972.                         ConvertMouseToXY(p, x2, y);
  973.                         if x2 > 252 then
  974.                             x2 := 252;
  975.                         if FirstTime then begin
  976.                                 x1 := x2;
  977.                                 FirstTime := false;
  978.                             end;
  979.                         if x2 >= x1 then
  980.                             for i := x1 to x2 + 3 do
  981.                                 with cTable[i].rgb do begin
  982.                                         red := bsl(255 - y, 8);
  983.                                         green := bsl(255 - y, 8);
  984.                                         blue := bsl(255 - y, 8);
  985.                                     end
  986.                         else
  987.                             for i := x1 + 3 downto x2 do
  988.                                 with cTable[i].rgb do begin
  989.                                         red := bsl(255 - y, 8);
  990.                                         green := bsl(255 - y, 8);
  991.                                         blue := bsl(255 - y, 8);
  992.                                     end;
  993.                         DrawMap;
  994.                         LoadLUT(cTable);
  995.                     end;
  996.                 if not isGrayscaleLut then
  997.                     LutMode := ColorLut;
  998.             end;
  999.     end;
  1000.  
  1001.  
  1002.     procedure DisableThresholding;
  1003.     begin
  1004.         with info^ do
  1005.             if thresholding then begin
  1006.                     ColorStart := SaveColorStart;
  1007.                     ColorEnd := SaveColorEnd;
  1008.                     FillColor1 := SaveFill1;
  1009.                     FillColor2 := SaveFill2;
  1010.                     UpdateMap;
  1011.                     UpdateLut;
  1012.                     Thresholding := false;
  1013.                 end;
  1014.     end;
  1015.  
  1016.  
  1017.     procedure EnableThresholding (level: integer);
  1018.     begin
  1019.         with info^ do begin
  1020.                 if thresholding then
  1021.                     DisableThresholding;
  1022.                 SaveColorStart := ColorStart;
  1023.                 SaveColorEnd := ColorEnd;
  1024.                 ColorStart := level;
  1025.                 ColorEnd := level;
  1026.                 SaveFill1 := FillColor1;
  1027.                 SaveFill2 := FillColor2;
  1028.                 FillColor1 := WhiteRGB;
  1029.                 FillColor2 := BlackRGB;
  1030.                 UpdateMap;
  1031.                 UpdateLut;
  1032.                 Thresholding := true;
  1033.                 if not macro then
  1034.                     SelectLutTool;
  1035.             end;
  1036.     end;
  1037.  
  1038.  
  1039.     procedure ResetMap;
  1040.     begin
  1041.         with info^ do begin
  1042.                 ColorStart := 0;
  1043.                 ColorEnd := 255;
  1044.                 if Thresholding then begin
  1045.                         FillColor1 := SaveFill1;
  1046.                         FillColor2 := SaveFill2;
  1047.                     end;
  1048.                 IdentityFunction := LutMode = Grayscale;
  1049.                 UpdateMap;
  1050.                 UpdateLUT;
  1051.             end;
  1052.     end;
  1053.  
  1054.  
  1055.     procedure DoMouseDownInMap;
  1056.         var
  1057.             r: rect;
  1058.             x, y, p1Dist, p2Dist: integer;
  1059.             mode: (StartPoint, EndPoint, Brightness, AdjustThreshold);
  1060.             p: point;
  1061.             pressed: boolean;
  1062.             x1, y1, x2, y2: integer;
  1063.             xintercept: integer;
  1064.             deltax, deltay: LongInt;
  1065.  
  1066.         procedure DoFixup;
  1067.         begin
  1068.             with info^ do
  1069.                 if ((x1 = 0) and (x2 = 0)) or ((x1 = 255) and (x2 = 255)) then begin
  1070.                         y1 := 0;
  1071.                         y2 := 255;
  1072.                     end;
  1073.         end;
  1074.  
  1075.     begin
  1076.         with info^ do begin
  1077.                 DisableDensitySlice;
  1078.                 if OptionKeyDown then begin
  1079.                         DoFreehandEditing;
  1080.                         exit(DoMouseDownInMap);
  1081.                     end;
  1082.                 if LUTMode = CustomGrayscale then
  1083.                     ResetGrayMap;
  1084.                 FindPoints(x1, y1, x2, y2);
  1085.                 SetPort(MapWindow);
  1086.                 GetMouse(p);
  1087.                 if PtInRect(p, gmIcon1) then begin
  1088.                         InvertRect(gmIcon1);
  1089.                         pressed := true;
  1090.                         while Button and pressed do begin
  1091.                                 GetMouse(p);
  1092.                                 if not PtInRect(p, gmIcon1) then begin
  1093.                                         InvertRect(gmIcon1);
  1094.                                         pressed := false;
  1095.                                     end;
  1096.                             end;
  1097.                         repeat
  1098.                         until not button;
  1099.                         if pressed then begin
  1100.                                 InvertRect(gmIcon1);
  1101.                                 ResetMap;
  1102.                                 exit(DoMouseDownInMap)
  1103.                             end;
  1104.                     end;
  1105.                 if PtInRect(p, gmIcon2) then begin
  1106.                         InvertRect(gmIcon2);
  1107.                         pressed := true;
  1108.                         while Button and pressed do begin
  1109.                                 GetMouse(p);
  1110.                                 if not PtInRect(p, gmIcon2) then begin
  1111.                                         InvertRect(gmIcon2);
  1112.                                         pressed := false;
  1113.                                     end;
  1114.                             end;
  1115.                         repeat
  1116.                         until not button;
  1117.                         if pressed then begin
  1118.                                 InvertRect(gmIcon2);
  1119.                                 if Thresholding then
  1120.                                     DisableThresholding
  1121.                                 else
  1122.                                     EnableThresholding(128);
  1123.                                 exit(DoMouseDownInMap)
  1124.                             end;
  1125.                     end;
  1126.                 if PtInRect(p, gmSlide1) then
  1127.                     AdjustBrightness;
  1128.                 if PtInRect(p, gmSlide2) then
  1129.                     AdjustContrast;
  1130.                 if p.v > (gmRectBottom + 4) then begin
  1131.                         if not thresholding and ((x2 - x1) <= 1) then begin
  1132.                                 thresholding := true;
  1133.                                 SaveFill1 := FillColor1;
  1134.                                 SaveFill2 := FillColor2;
  1135.                             end;
  1136.                         exit(DoMouseDownInMap);
  1137.                     end;
  1138.                 if LutMode = CustomGrayscale then
  1139.                     LutMode := Grayscale;
  1140.                 GetMouse(p);
  1141.                 ConvertMouseToXY(p, x, y);
  1142.                 if (x <= 24) or (y <= 32) then
  1143.                     mode := StartPoint
  1144.                 else if (x >= 224) or (y >= 232) then
  1145.                     mode := EndPoint
  1146.                 else if thresholding then
  1147.                     mode := AdjustThreshold
  1148.                 else
  1149.                     mode := brightness;
  1150.                 if mode = AdjustThreshold then
  1151.                     DrawLabels('Thresh:', '', '')
  1152.                 else
  1153.                     ShowLabels;
  1154.                 repeat
  1155.                     case mode of
  1156.                         StartPoint:  begin
  1157.                                 if thresholding then begin
  1158.                                         FillColor1 := SaveFill1;
  1159.                                         FillColor2 := SaveFill2;
  1160.                                     end;
  1161.                                 if x > y then
  1162.                                     y := 0
  1163.                                 else
  1164.                                     x := 0;
  1165.                                 x1 := x;
  1166.                                 if x1 > x2 then
  1167.                                     x2 := x1;
  1168.                                 y1 := y;
  1169.                                 if y1 > y2 then
  1170.                                     y2 := y1;
  1171.                                 DoFixUp;
  1172.                             end;
  1173.                         EndPoint:  begin
  1174.                                 if thresholding then begin
  1175.                                         FillColor1 := SaveFill1;
  1176.                                         FillColor2 := SaveFill2;
  1177.                                     end;
  1178.                                 if x > y then
  1179.                                     x := 255
  1180.                                 else
  1181.                                     y := 255;
  1182.                                 x2 := x;
  1183.                                 if x2 < x1 then
  1184.                                     x1 := x2;
  1185.                                 y2 := y;
  1186.                                 if y2 < y1 then
  1187.                                     y1 := y2;
  1188.                                 DoFixUp;
  1189.                             end;
  1190.                         Brightness:  begin
  1191.                                 deltax := x2 - x1;
  1192.                                 deltay := y2 - y1;
  1193.                                 if deltax = 0 then begin
  1194.                                         x1 := x;
  1195.                                         y1 := 0;
  1196.                                         x2 := x;
  1197.                                         y2 := 255;
  1198.                                     end
  1199.                                 else if deltay = 0 then begin
  1200.                                         x1 := 0;
  1201.                                         y1 := y;
  1202.                                         x2 := 255;
  1203.                                         y2 := y;
  1204.                                     end
  1205.                                 else begin
  1206.                                         x1 := x - y * deltax div deltay;
  1207.                                         xIntercept := x1;
  1208.                                         y1 := 0;
  1209.                                         if x1 < 0 then begin
  1210.                                                 y1 := -deltay * x1 div deltaX;
  1211.                                                 x1 := 0;
  1212.                                             end;
  1213.                                         y2 := 255;
  1214.                                         x2 := 255 * deltax div deltay;
  1215.                                         if xIntercept < 0 then
  1216.                                             x2 := x2 + xIntercept
  1217.                                         else
  1218.                                             x2 := x2 + x1;
  1219.                                         if x2 > 255 then begin
  1220.                                                 y2 := 255 - (x2 - 255) * deltay div deltax;
  1221.                                                 x2 := 255;
  1222.                                             end;
  1223.                                     end;
  1224.                                 if x2 < 1 then
  1225.                                     x2 := 1;
  1226.                                 if y2 < 1 then
  1227.                                     y2 := 1;
  1228.                                 if x1 > 254 then
  1229.                                     x1 := 254;
  1230.                                 if y1 > 254 then
  1231.                                     y1 := 254;
  1232.                             end;
  1233.                         AdjustThreshold:  begin
  1234.                                 x1 := x;
  1235.                                 y1 := 0;
  1236.                                 x2 := x;
  1237.                                 y2 := 255;
  1238.                             end;
  1239.                     end; {case}
  1240. {showmessage(concat(long2str(x1), '  ', long2str(y1), '  ', long2str(x2), '  ', long2str(y2), cr, long2str(ColorStart), '  ', long2str(ColorEnd)));}
  1241.                     if y1 = 0 then
  1242.                         ColorStart := x1
  1243.                     else begin
  1244.                             if (y2 > y1) then
  1245.                                 ColorStart := -LongInt(x2 - x1) * y1 div (y2 - y1)
  1246.                             else
  1247.                                 ColorStart := -MaxColor;
  1248.                         end;
  1249.                     if y2 = 255 then
  1250.                         ColorEnd := x2
  1251.                     else begin
  1252.                             if (y2 > y1) then
  1253.                                 ColorEnd := 255 + LongInt(x2 - x1) * (255 - y2) div ((y2 - y1))
  1254.                             else
  1255.                                 ColorEnd := MaxColor;
  1256.                         end;
  1257.                     UpdateMap;
  1258.                     UpdateLUT;
  1259.                     if thresholding then
  1260.                         Show1Value(ColorStart, NoValue)
  1261.                     else
  1262.                         ShowLUTValues(ColorStart, ColorEnd);
  1263.                     GetMouse(p);
  1264.                     ConvertMouseToXY(p, x, y);
  1265.                 until not Button;
  1266.                 IdentityFunction := false;
  1267.                 if not thresholding and ((x2 - x1) <= 1) then begin
  1268.                         thresholding := true;
  1269.                         SaveFill1 := FillColor1;
  1270.                         SaveFill2 := FillColor2;
  1271.                     end;
  1272.             end; {with info}
  1273.     end;
  1274.  
  1275.  
  1276.     procedure DrawLUT;
  1277.         var
  1278.             tPort: GrafPtr;
  1279.             h, v, i: integer;
  1280.     begin
  1281.         GetPort(tPort);
  1282.         SetPort(LUTWindow);
  1283.         with LutWindow^ do begin
  1284.                 for v := 0 to 255 do begin
  1285.                         pmForeColor(v);
  1286.                         MoveTo(0, v);
  1287.                         LineTo(cwidth, v)
  1288.                     end;
  1289.                 for i := 1 to nExtraColors + 2 do begin
  1290.                         pmForeColor(ExtraColorsEntry[i]);
  1291.                         PaintRect(ExtraColorsRect[i]);
  1292.                     end;
  1293.                 TextFont(ApplFont);
  1294.                 TextSize(9);
  1295.                 with ExtraColorsRect[1] do
  1296.                     MoveTo(left + 3, bottom - 1);
  1297.                 pmForeColor(BlackIndex);
  1298.                 DrawString('white');
  1299.                 with ExtraColorsRect[2] do
  1300.                     MoveTo(left + 4, bottom - 1);
  1301.                 InvertRect(ExtraColorsRect[2]);
  1302.                 DrawString('black');
  1303.                 InvertRect(ExtraColorsRect[2]);
  1304.             end;
  1305.         SetPort(tPort);
  1306.     end;
  1307.  
  1308.  
  1309.     function LoadPP2Palette: boolean;
  1310. {Loads COLR resource from PixelPaint 2.0 palette file.}
  1311.         var
  1312.             i: integer;
  1313.             size: LongInt;
  1314.             h: Handle;
  1315.             PPColorTable: record
  1316.                     ctSize: INTEGER;
  1317.                     table: array[0..255] of RGBColor;
  1318.                 end;
  1319.     begin
  1320.         h := GetResource('COLR', 999);
  1321.         size := GetHandleSize(handle(h));
  1322.         if (ResError = NoErr) and (size = 1538) then
  1323.             with info^ do begin
  1324.                     BlockMove(handle(h)^, @PPColorTable, SizeOf(PPColorTable));
  1325.                     with PPColorTable do begin
  1326.                             for i := 0 to 255 do
  1327.                                 cTable[i].rgb := table[i];
  1328.                         end;
  1329.                     LoadLUT(cTable);
  1330.                     LutMode := ColorLut;
  1331.                     SetupPseudocolor;
  1332.                     IdentityFunction := false;
  1333.                     LoadPP2Palette := true;
  1334.                 end
  1335.         else
  1336.             LoadPP2Palette := false;
  1337.         if h <> nil then
  1338.             DisposHandle(h);
  1339.     end;
  1340.  
  1341.  
  1342.     procedure LoadColorTable (theColorTable: CTabHandle);
  1343.         const
  1344.             ExpectedSize = 2056;
  1345.         var
  1346.             size: LongInt;
  1347.             MyColorTable: record
  1348.                     ctSeed: LONGINT;
  1349.                     transIndex: INTEGER;
  1350.                     ctSize: INTEGER;
  1351.                     ctTable: MyCSpecArray;
  1352.                 end;
  1353.     begin
  1354.         size := GetHandleSize(handle(theColorTable));
  1355.         if size < ExpectedSize then
  1356.             exit(LoadColorTable);
  1357.         if size > ExpectedSize then
  1358.             Size := ExpectedSize;
  1359.         BlockMove(handle(theColorTable)^, @MyColorTable, size);
  1360.         LoadLUT(MyColorTable.ctTable);
  1361.         with info^ do begin
  1362.                 cTable := MyColorTable.ctTable;
  1363.                 LutMode := ColorLut;
  1364.                 IdentityFunction := false;
  1365.             end;
  1366.         SetupPseudocolor;
  1367.     end;
  1368.  
  1369.  
  1370.     function LoadCLUTResource;{(id:integer):boolean}
  1371.         const
  1372.             ExpectedSize = 2056;
  1373.         var
  1374.             Size: LongInt;
  1375.             h: cTabHandle;
  1376.     begin
  1377.         DisableDensitySlice;
  1378.         h := GetCTable(id);
  1379.         size := GetHandleSize(handle(h));
  1380.         if (ResError <> NoErr) or (size < ExpectedSize) then begin
  1381.                 LoadCLUTResource := false;
  1382.                 if id = PixelpaintID then begin
  1383.                         if LoadPP2Palette then
  1384.                             LoadCLUTResource := true;
  1385.                     end;
  1386.                 if h <> nil then
  1387.                     DisposCTable(h);
  1388.                 exit(LoadCLUTResource)
  1389.             end;
  1390.         LoadColorTable(h);
  1391.         DisposCTable(h);
  1392.         LoadCLUTResource := true;
  1393.     end;
  1394.  
  1395.  
  1396.     procedure GetLookupTable;{(VAR table:LookupTable)}
  1397.         var
  1398.             i, r, g, b: integer;
  1399.             GrayscaleImage: boolean;
  1400.     begin
  1401.         with info^ do begin
  1402.                 if DensitySlicing then begin
  1403.                         for i := 0 to 255 do
  1404.                             if (i >= SliceStart) and (i <= SliceEnd) then begin
  1405.                                     if ThresholdToForeground then
  1406.                                         table[i] := ForegroundIndex
  1407.                                     else
  1408.                                         table[i] := i
  1409.                                 end
  1410.                             else begin
  1411.                                     if NonThresholdToBackground then
  1412.                                         table[i] := BackgroundIndex
  1413.                                     else
  1414.                                         table[i] := i
  1415.                                 end;
  1416.                         DisableDensitySlice;
  1417.                         exit(GetLookupTable);
  1418.                     end;
  1419.                 if (LutMode = GrayScale) or (LutMode = CustomGrayscale) then
  1420.                     for i := 0 to 255 do
  1421.                         table[i] := 255 - BSR(cTable[i].RGB.red, 8)
  1422.                 else begin
  1423.                         table[0] := 0;
  1424.                         for i := 1 to 254 do
  1425.                             with cTable[i].RGB do
  1426.                                 table[i] := 255 - trunc(band(bsr(red, 8), 255) * 0.3 + band(bsr(green, 8), 255) * 0.59 + band(bsr(blue, 8), 255) * 0.11);
  1427.                         table[255] := 255;
  1428.                     end;
  1429.             end; {with}
  1430.     end;
  1431.  
  1432.  
  1433.     procedure RedrawLUTWindow;
  1434.     begin
  1435.         LoadLUT(info^.cTable);
  1436.         cheight := 256 + (2 + nExtraColors) * ExtraColorsHeight;
  1437.         SizeWindow(LUTWindow, cwidth, cheight, true);
  1438.     end;
  1439.  
  1440.  
  1441.     procedure DrawDensitySlice (OptionKey: boolean);
  1442.         var
  1443.             i, tRed: integer;
  1444.     begin
  1445.         with info^ do begin
  1446.                 if OptionKey then begin
  1447.                         UndoLutChange;
  1448.                         exit(DrawDensitySlice);
  1449.                     end
  1450.                 else
  1451.                     for i := 0 to 255 do
  1452.                         if (i >= SliceStart) and (i <= SliceEnd) then
  1453.                             cTable[i].rgb := SliceColor
  1454.                         else
  1455.                             ctable[i].rgb := UndoInfo^.cTable[i].rgb;
  1456.                 LoadLUT(cTable);
  1457.             end;
  1458.     end;
  1459.  
  1460.  
  1461.     procedure SelectLutTool;
  1462.         var
  1463.             tPort: GrafPtr;
  1464.     begin
  1465.         if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
  1466.                 GetPort(tPort);
  1467.                 SetPort(ToolWindow);
  1468.                 InvalRect(ToolRect[CurrentTool]);
  1469.                 InvalRect(ToolRect[LutTool]);
  1470.                 CurrentTool := LutTool;
  1471.                 isSelectionTool := false;
  1472.                 SetPort(tPort);
  1473.             end;
  1474.     end;
  1475.  
  1476.  
  1477.     procedure EnableDensitySlice;
  1478.     begin
  1479.         if not DensitySlicing then begin
  1480.                 SetupLutUndo;
  1481.                 DrawDensitySlice(false);
  1482.                 DensitySlicing := true;
  1483.                 SelectLUTTool;
  1484.             end;
  1485.     end;
  1486.  
  1487.  
  1488.     procedure DoImportLut (fname: str255; vnum: integer);
  1489.         var
  1490.             err: OSErr;
  1491.             f, i: integer;
  1492.             ByteCount: LongInt;
  1493.             ImportedLUT: array[1..3] of packed array[0..255] of byte;
  1494.     begin
  1495.         DisableDensitySlice;
  1496.         err := fsopen(fname, vNum, f);
  1497.         ByteCount := 768;
  1498.         err := fsRead(f, ByteCount, @ImportedLUT);
  1499.         if err = NoErr then
  1500.             with info^ do begin
  1501.                     for i := 0 to 255 do
  1502.                         with cTable[i], cTable[i].rgb do begin
  1503.                                 value := 0;
  1504.                                 red := bsl(ImportedLUT[1, i], 8);
  1505.                                 green := bsl(ImportedLUT[2, i], 8);
  1506.                                 blue := bsl(ImportedLUT[3, i], 8);
  1507.                             end;
  1508.                     LoadLUT(cTable);
  1509.                     SetupPseudocolor;
  1510.                     LutMode := PseudoColor;
  1511.                     IdentityFunction := false;
  1512.                     if isGrayScaleLUT then
  1513.                         info^.LutMode := CustomGrayScale;
  1514.                     UpdateMap;
  1515.                 end
  1516.         else
  1517.             beep;
  1518.         err := fsClose(f);
  1519.     end;
  1520.  
  1521.  
  1522.     procedure OpenOldPalette (fname: str255; RefNum: integer);
  1523. {Opens palette files created by versions Image earlier than 1.42.}
  1524.         var
  1525.             PaletteHeader: ColorArray;
  1526.             err, f, ColorWidth: integer;
  1527.             size: LongInt;
  1528.     begin
  1529.         DisableDensitySlice;
  1530.         err := fsopen(fname, RefNum, f);
  1531.         with info^ do begin
  1532.                 size := SizeOf(ColorArray);
  1533.                 err := fsread(f, size, @PaletteHeader);
  1534.                 nColors := PaletteHeader[0];
  1535.                 if nColors > MaxPseudocolors then
  1536.                     nColors := MaxPseudoColors;
  1537.                 ColorEnd := 255 - PaletteHeader[1];
  1538.                 ColorWidth := PaletteHeader[2];
  1539.                 ColorStart := ColorEnd - nColors * ColorWidth + 1;
  1540.                 if ColorStart < 0 then
  1541.                     ColorStart := 0;
  1542.                 FillColor1 := BlackRGB;
  1543.                 FillColor2 := BlackRGB;
  1544.                 err := fsread(f, size, @RedLut);
  1545.                 err := fsread(f, size, @GreenLut);
  1546.                 err := fsread(f, size, @BlueLut);
  1547.                 LutMode := PseudoColor;
  1548.                 InvertedColorTable := false;
  1549.             end;
  1550.         err := fsclose(f);
  1551.         UpdateLUT;
  1552.     end;
  1553.  
  1554.  
  1555.     procedure OpenNewPalette (fname: str255; RefNum: integer);
  1556. {Opens palette files created by versions of Image later than 1.41.}
  1557.         var
  1558.             err, f: integer;
  1559.             count: LongInt;
  1560.             hdr: PaletteHeader;
  1561.     begin
  1562.         DisableDensitySlice;
  1563.         err := fsopen(fname, RefNum, f);
  1564.         with info^ do begin
  1565.                 count := SizeOf(PaletteHeader);
  1566.                 err := fsread(f, count, @hdr);
  1567.                 with hdr do begin
  1568.                         nColors := pnColors;
  1569.                         if nColors > 256 then
  1570.                             nColors := 256;
  1571.                         ColorStart := pColorStart;
  1572.                         ColorEnd := pColorEnd;
  1573.                         FillColor1 := pFill1;
  1574.                         FillColor2 := pFill2;
  1575.                         InvertedColorTable := false;
  1576.                     end;
  1577.                 count := nColors;
  1578.                 err := fsread(f, count, @RedLut);
  1579.                 count := nColors;
  1580.                 err := fsread(f, count, @GreenLut);
  1581.                 count := nColors;
  1582.                 err := fsread(f, count, @BlueLut);
  1583.                 LutMode := PseudoColor;
  1584.             end;
  1585.         err := fsclose(f);
  1586.         UpdateLUT;
  1587.     end;
  1588.  
  1589.  
  1590.     procedure OpenColorTable (fname: str255; RefNum: integer);
  1591.         var
  1592.             err: OSErr;
  1593.             f: integer;
  1594.             FileSize, count: LongInt;
  1595.             id: packed array[1..4] of char;
  1596.     begin
  1597.         err := fsopen(fname, RefNum, f);
  1598.         err := GetEOF(f, FileSize);
  1599.         count := SizeOf(id);
  1600.         err := fsread(f, count, @id);
  1601.         err := fsclose(f);
  1602.         if FileSize = 768 then
  1603.             DoImportLut(fname, RefNum)
  1604.         else if id = 'ICOL' then
  1605.             OpenNewPalette(fname, RefNum)
  1606.         else
  1607.             OpenOldPalette(fname, RefNum);
  1608.     end;
  1609.  
  1610.  
  1611.     procedure ImportPalette (FileType: OSType; fname: str255; vnum: integer);
  1612.         var
  1613.             RefNum: integer;
  1614.             ok: boolean;
  1615.             err: OSErr;
  1616.     begin
  1617.         err := SetVol(nil, vnum);
  1618.         refNum := OpenResFile(fname);
  1619.         if RefNum <> -1 then begin
  1620.                 if FileType = 'CLUT' then
  1621.                     ok := LoadClutResource(KlutzID)
  1622.                 else
  1623.                     ok := LoadClutResource(PixelPaintID); {Load PixelPaint or Canvas palette}
  1624.                 CloseResFile(RefNum);
  1625.                 if isGrayScaleLUT then begin
  1626.                         info^.LutMode := CustomGrayScale;
  1627.                         DrawMap;
  1628.                     end;
  1629.             end;
  1630.     end;
  1631.  
  1632.  
  1633.     procedure InitPaletteHeader (var hdr: PaletteHeader);
  1634.         var
  1635.             i: integer;
  1636.     begin
  1637.         with hdr, info^ do begin
  1638.                 pID := 'ICOL';
  1639.                 pVersion := version;
  1640.                 pnColors := nColors;
  1641.                 pColorStart := ColorStart;
  1642.                 pColorEnd := ColorEnd;
  1643.                 pFill1 := FillColor1;
  1644.                 pFill2 := FillColor2;
  1645.                 for i := 1 to 4 do
  1646.                     pUnused[i] := 0;
  1647.             end;
  1648.     end;
  1649.  
  1650.  
  1651.     procedure SaveLutResource;
  1652. {Saves the current color table as  a CPAL resource}
  1653.         var
  1654.             id: integer;
  1655.             canceled: boolean;
  1656.             PalH: handle;
  1657.             hdr: PaletteHeader;
  1658.             p: ptr;
  1659.     begin
  1660.         with info^ do begin
  1661.                 id := GetInt('Resource ID', 1000, canceled);
  1662.                 if canceled then
  1663.                     exit(SaveLutResource);
  1664.                 PalH := GetResource('CPAL', id);
  1665.                 if GetHandleSize(PalH) > 0 then begin
  1666.                         RmveResource(PalH);
  1667.                         DisposHandle(PalH);
  1668.                     end;
  1669.                 InitPaletteHeader(hdr);
  1670.                 PalH := NewHandle(SizeOF(PaletteHeader) + nColors * 3);
  1671.                 p := PalH^;
  1672.                 BlockMove(@hdr, p, SizeOf(PaletteHeader));
  1673.                 p := ptr(ord4(p) + SizeOf(PaletteHeader));
  1674.                 BlockMove(@RedLut, p, nColors);
  1675.                 p := ptr(ord4(p) + nColors);
  1676.                 BlockMove(@GreenLut, p, nColors);
  1677.                 p := ptr(ord4(p) + nColors);
  1678.                 BlockMove(@BlueLut, p, nColors);
  1679.                 AddResource(PalH, 'CPAL', id, '');
  1680.                 WriteResource(PalH);
  1681.                 if ResError <> NoErr then
  1682.                     SysBeep(1);
  1683.                 DisposHandle(PalH);
  1684.             end;
  1685.     end;
  1686.  
  1687.  
  1688.     procedure GetLutResource (id: integer);
  1689.         var
  1690.             LutH: handle;
  1691.             hdr: PaletteHEader;
  1692.             p: ptr;
  1693.     begin
  1694.         with info^ do begin
  1695.                 LutH := GetResource('CPAL', id);
  1696.                 if (ResError <> noErr) or (LutH = nil) then begin
  1697.                         beep;
  1698.                         if LutH <> nil then
  1699.                             ReleaseResource(LutH);
  1700.                         exit(GetLutResource)
  1701.                     end;
  1702.                 p := LutH^;
  1703.                 BlockMove(p, @hdr, SizeOf(PaletteHeader));
  1704.                 with hdr do begin
  1705.                         if pID <> 'ICOL' then begin
  1706.                                 beep;
  1707.                                 ReleaseResource(LutH);
  1708.                                 exit(GetLutResource);
  1709.                             end;
  1710.                         nColors := pnColors;
  1711.                         if nColors > 256 then
  1712.                             nColors := 256;
  1713.                         ColorStart := pColorStart;
  1714.                         ColorEnd := pColorEnd;
  1715.                         FillColor1 := pFill1;
  1716.                         FillColor2 := pFill2;
  1717.                         InvertedColorTable := false;
  1718.                     end;
  1719.                 p := ptr(ord4(p) + SizeOf(PaletteHeader));
  1720.                 BlockMove(p, @RedLut, nColors);
  1721.                 p := ptr(ord4(p) + nColors);
  1722.                 BlockMove(p, @GreenLut, nColors);
  1723.                 p := ptr(ord4(p) + nColors);
  1724.                 BlockMove(p, @BlueLut, nColors);
  1725.                 ReleaseResource(LutH);
  1726.             end;
  1727.     end;
  1728.  
  1729.  
  1730.     procedure DrawScale;
  1731.         var
  1732.             hloc, vloc, width, height, SaveForeground, LUTStart, LutEnd, LUTWidth: integer;
  1733.     begin
  1734.         if NoSelection or NotRectangular then
  1735.             exit(DrawScale);
  1736.         ShowWatch;
  1737.         with info^.RoiRect, info^ do begin
  1738.                 width := right - left;
  1739.                 height := bottom - top;
  1740.                 if (width = 0) or (height = 0) then
  1741.                     exit(DrawScale);
  1742.                 SetPort(GrafPtr(osPort));
  1743.                 PenNormal;
  1744.                 SetupUndoFromClip;
  1745.                 SetupUndo;
  1746.                 WhatToUndo := UndoEdit;
  1747.                 SaveForeground := ForegroundIndex;
  1748.                 LUTStart := ColorStart;
  1749.                 if LutStart <= 0 then
  1750.                     LutStart := 1;
  1751.                 LutEnd := ColorEnd;
  1752.                 if LutEnd >= 255 then
  1753.                     LutEnd := 254;
  1754.                 LUTWidth := LutEnd - LutStart + 1;
  1755.                 if width >= height then
  1756.                     for hloc := left to right - 1 do begin
  1757.                             SetForegroundColor(trunc(((hloc - left) / width) * LUTWidth) + LUTStart);
  1758.                             MoveTo(hloc, top);
  1759.                             LineTo(hloc, Bottom - 1);
  1760.                         end
  1761.                 else
  1762.                     for vloc := top to bottom - 1 do begin
  1763.                             SetForegroundColor(trunc(((vloc - top) / height) * LUTWidth) + LUTStart);
  1764.                             MoveTo(left, vloc);
  1765.                             LineTo(right - 1, vloc);
  1766.                         end;
  1767.                 SetForegroundColor(SaveForeground);
  1768.                 changes := true;
  1769.             end;
  1770.         SetupRoiRect;
  1771.     end;
  1772.  
  1773.  
  1774.     procedure MakeSpectrum;
  1775.   {Generates the "Spectrum" color table.}
  1776.         const
  1777.             Sat = -1;
  1778.             Val = -1;
  1779.         var
  1780.             i: integer;
  1781.             color: HSVColor;
  1782.     begin
  1783.         with info^ do begin
  1784.                 for i := 0 to 255 do begin
  1785.                         color.hue := i * 256;
  1786.                         color.saturation := sat;
  1787.                         color.value := val;
  1788.                         HSV2RGB(color, ctable[i].rgb);
  1789.                     end;
  1790.                 LutMode := ColorLut;
  1791.                 IdentityFunction := false;
  1792.                 SetupPseudocolor;
  1793.             end;
  1794.     end;
  1795.  
  1796.  
  1797.     function GetColorTableItem (ctab: ColorTableType): integer;
  1798.     begin
  1799.         case ctab of
  1800.             AppleDefault: 
  1801.                 GetColorTableItem := SystemPaletteItem;
  1802.             Pseudo20: 
  1803.                 GetColorTableItem := Pseudo20Item;
  1804.             Pseudo32: 
  1805.                 GetColorTableItem := Pseudo32Item;
  1806.             Rainbow: 
  1807.                 GetColorTableItem := RainbowItem;
  1808.             Fire1: 
  1809.                 GetColorTableItem := Fire1Item;
  1810.             Fire2: 
  1811.                 GetColorTableItem := Fire2Item;
  1812.             Ice: 
  1813.                 GetColorTableItem := IceItem;
  1814.             Grays: 
  1815.                 GetColorTableItem := GraysItem;
  1816.             Spectrum: 
  1817.                 GetColorTableItem := SpectrumItem;
  1818.             otherwise
  1819.                 GetColorTableItem := Pseudo20Item;
  1820.         end;
  1821.     end;
  1822.  
  1823.  
  1824.     procedure SwitchColorTables (item: integer; update: boolean);
  1825.         var
  1826.             ok: boolean;
  1827.     begin
  1828.         DisableDensitySlice;
  1829.         if update then
  1830.             SetupLutUndo;
  1831.         with info^ do begin
  1832.                 case item of
  1833.                     SystemPaletteItem:  begin
  1834.                             ok := LoadCLUTResource(AppleDefaultCLUT);
  1835.                             ColorTable := AppleDefault;
  1836.                         end;
  1837.                     Pseudo20Item:  begin
  1838.                             GetLutResource(Pseudo20ID);
  1839.                             ColorTable := Pseudo20;
  1840.                         end;
  1841.                     Pseudo32Item:  begin
  1842.                             GetLutResource(Pseudo32ID);
  1843.                             ColorTable := Pseudo32;
  1844.                         end;
  1845.                     RainbowItem:  begin
  1846.                             GetLutResource(RainbowID);
  1847.                             ColorTable := Rainbow;
  1848.                         end;
  1849.                     Fire1Item:  begin
  1850.                             GetLutResource(Fire1ID);
  1851.                             ColorTable := Fire1;
  1852.                         end;
  1853.                     Fire2Item:  begin
  1854.                             GetLutResource(Fire2ID);
  1855.                             ColorTable := Fire2;
  1856.                         end;
  1857.                     IceItem:  begin
  1858.                             GetLutResource(IceID);
  1859.                             ColorTable := Ice;
  1860.                         end;
  1861.                     GraysItem:  begin
  1862.                             GetLutResource(GraysID);
  1863.                             ColorTable := Grays;
  1864.                         end;
  1865.                     SpectrumItem: 
  1866.                         if ControlKeyDown and OptionKeyDown and ShiftKeyDown then
  1867.                             SaveLutResource
  1868.                         else begin
  1869.                                 MakeSpectrum;
  1870.                                 ColorTable := Spectrum;
  1871.                             end;
  1872.                 end; {case}
  1873.                 LutMode := Pseudocolor;
  1874.                 if update then begin
  1875.                         UpdateLUT;
  1876.                         UpdateMap;
  1877.                     end;
  1878.             end;
  1879.     end;
  1880.  
  1881.  
  1882.     procedure SetNumberOfColors (n: integer);
  1883.         var
  1884.             i, r, g, b, index: integer;
  1885.             eIndex, inc, fraction: extended;
  1886.             SaveRed, SaveGreen, SaveBlue: LutArray;
  1887.     begin
  1888.         with info^ do begin
  1889.                 SaveRed := RedLUT;
  1890.                 SaveGreen := GreenLUT;
  1891.                 SaveBlue := BlueLUT;
  1892.                 eIndex := 0.0;
  1893.                 inc := (nColors - 1) / (n - 1);
  1894.                 for i := 0 to n - 1 do begin
  1895.                         index := trunc(eIndex);
  1896.                         if index >= (nColors - 1) then begin
  1897.                                 RedLUT[i] := SaveRed[index];
  1898.                                 GreenLUT[i] := SaveGreen[index];
  1899.                                 BlueLUT[i] := SaveBlue[index]
  1900.                             end
  1901.                         else begin
  1902.                                 fraction := eIndex - index;
  1903.                                 RedLUT[i] := round(SaveRed[index] * (1.0 - fraction) + SaveRed[index + 1] * fraction);
  1904.                                 GreenLUT[i] := round(SaveGreen[index] * (1.0 - fraction) + SaveGreen[index + 1] * fraction);
  1905.                                 BlueLUT[i] := round(SaveBlue[index] * (1.0 - fraction) + SaveBlue[index + 1] * fraction);
  1906.                             end;
  1907.                         eIndex := eIndex + inc;
  1908.                     end;
  1909.                 nColors := n;
  1910.                 LutMode := PseudoColor;
  1911.                 ColorTable := CustomTable;
  1912.                 UpdateLUT;
  1913.                 UpdateMap;
  1914.             end;
  1915.     end;
  1916.  
  1917.  
  1918.     procedure SetNumberOfExtraColors;
  1919.         var
  1920.             n: integer;
  1921.             Canceled: boolean;
  1922.     begin
  1923.         n := GetInt('Number of Extra Colors(0..6):', nExtraColors, Canceled);
  1924.         if (n <= 6) and (n >= 0) and not Canceled then begin
  1925.                 nExtraColors := n;
  1926.                 RedrawLUTWindow;
  1927.                 SelectWindow(LUTWindow);
  1928.                 if info <> NoInfo then
  1929.                     SelectWindow(info^.wptr);
  1930.             end
  1931.         else if not Canceled then
  1932.             beep;
  1933.     end;
  1934.  
  1935.  
  1936.     procedure DoLutOptions;
  1937.         const
  1938.             nColorsID = 7;
  1939.             nExtraColorsID = 8;
  1940.             InvertID = 9;
  1941.         var
  1942.             mylog: DialogPtr;
  1943.             item, i, n, nExtra: integer;
  1944.             InvertLut: boolean;
  1945.     begin
  1946.         with info^ do begin
  1947.                 InitCursor;
  1948.                 mylog := GetNewDialog(210, nil, pointer(-1));
  1949.                 n := nColors;
  1950.                 SetDNum(MyLog, nColorsID, n);
  1951.                 nExtra := nExtraColors;
  1952.                 SetDNum(MyLog, nExtraColorsID, nExtra);
  1953.                 InvertLut := false;
  1954.                 SetDialogItem(mylog, InvertID, ord(InvertLut));
  1955.                 repeat
  1956.                     ModalDialog(nil, item);
  1957.                     if item = nColorsID then
  1958.                         n := GetDNum(MyLog, nColorsID);
  1959.                     if item = nExtraColorsID then
  1960.                         nExtra := GetDNum(MyLog, nExtraColorsID);
  1961.                     if item = InvertID then begin
  1962.                             InvertLut := not InvertLut;
  1963.                             SetDialogItem(mylog, InvertID, ord(InvertLut));
  1964.                         end;
  1965.                 until (item = ok) or (item = cancel);
  1966.                 DisposDialog(mylog);
  1967.                 if item = cancel then
  1968.                     exit(DoLutOptions);
  1969.                 DisableDensitySlice;
  1970.                 SetupLutUndo;
  1971.                 if n < 1 then
  1972.                     n := 1;
  1973.                 if n > 256 then
  1974.                     n := 256;
  1975.                 if n <> nColors then
  1976.                     SetNumberOfColors(n);
  1977.                 if (nExtra <> nExtraColors) and (nExtra >= 0) and (nExtra <= 6) then begin
  1978.                         nExtraColors := nExtra;
  1979.                         RedrawLUTWindow;
  1980.                         SelectWindow(LUTWindow);
  1981.                         if info <> NoInfo then
  1982.                             SelectWindow(info^.wptr);
  1983.                     end;
  1984.                 if InvertLut then begin
  1985.                         InvertPalette;
  1986.                         UpdateLut;
  1987.                     end;
  1988.             end; {with info}
  1989.     end;
  1990.  
  1991.  
  1992. end.